#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SkeletonAnimationReader.h"
#include "FileReader.h"

SkeletonAnimation * SkeletonAnimationReader::LoadFromFile(char * fileName, char ** name)
{
	FILE * fptr = NULL;
	if((fptr = fopen(fileName, "r")) == NULL)
	{
		printf("Error opening skeleton animation file -%s-\n", fileName);
		return NULL;
	}
	
	char * tag;
	(*name) = NULL;
	SkeletonAnimation * animation = NULL;
	while((tag = FileReader::GetNextTag(fptr)) != NULL)
	{
		printf("TAG: %s\n", tag);
		//read through the tag, one element at a time
		int pos = 0;		
		char * element = FileReader::GetNextElement(tag, &pos);
		
		printf("ELEMENT: %s\n", element);
		
		switch(GetElementType(element))
		{
			case ANIMATION_NAME_TYPE: 
				(*name) = HandleNameTag(tag,pos);
				break;
			case POSE_TYPE:
				BoneOrientationNode * pose = HandlePoseTag(tag,pos);
				if(animation)
					animation->Add(pose);
				else
					animation = new SkeletonAnimation(pose);
				break;
		}
		if(element != NULL)
			free(element);
		element = NULL;
		if(tag != NULL)
			free(tag);
		tag = NULL;
	}
	fclose(fptr);	
	return animation;
}
char * SkeletonAnimationReader::HandleNameTag(char * tag, int pos)
{
	char * name = FileReader::ReadNextString(tag, &pos);
	return name;	
}
BoneOrientationNode * SkeletonAnimationReader::HandlePoseTag(char * tag, int pos)
{
	return ReadNextPose(tag, &pos);
}
BoneOrientationNode * SkeletonAnimationReader::ReadNextPose(char * tag, int * pos)
{
	BoneOrientation * boneOrientation = ReadNextBoneOrientation(tag, pos);
	int numOutgoingBones = FileReader::ReadNextInt(tag, pos);
	BoneOrientationNode * node = new BoneOrientationNode(boneOrientation);
	BoneOrientationNodeList * list = new BoneOrientationNodeList();
	for(int i = 0; i < numOutgoingBones; i++)
		list->Add(ReadNextPose(tag, pos));
		
	List<BoneOrientationNode> * search = list->head;
	while(search)
	{
		node->Add(search->payload);
		search = search->next;	
	}
	return node;
}
BoneOrientation * SkeletonAnimationReader::ReadBoneOrientation(char * element)
{
	float length = 0.0;
	float lengthCoefficient = 0.0;
	float lengthSpeed = 0.0;
	float lengthSpeedCoefficient = 0.0;
	float angle = 0.0;
	float angleCoefficient = 0.0;
    float speed = 0.0;
    float speedCoefficient = 0.0;
 	float time = 0.0;
 	float timeCoefficient = 0.0;
 	float width = 0.0;
 	BoneOrientation * orientation = NULL;
 	printf("Trying to Read BoneOrientation\n");
	if(sscanf(element, "(%f,%f,%f,%f,%f,%f,%f,%f,%f,%f)", &length, &lengthCoefficient,
														  &lengthSpeed, &lengthSpeedCoefficient,
														  &angle, &angleCoefficient,
														  &speed, &speedCoefficient,
														  &time, &timeCoefficient) == 10)
	{
		printf("Reading BoneOrientation1\n");
		orientation = new BoneOrientation( length, lengthCoefficient,
										  lengthSpeed, lengthSpeedCoefficient,
										  angle, angleCoefficient,
										  speed, speedCoefficient,
										  time, timeCoefficient);
	}
	else if(sscanf(element, "(%f,%f,%f,%f,%f)", &length, &angle, &lengthSpeed, &speed, &time) == 5)
	{
		printf("Reading BoneOrientation width = %f, time = %f\n", width, time);
		orientation = new BoneOrientation(length, angle, lengthSpeed,
										  speed, time);
	}
	else if(sscanf(element, "(%f,%f,%f)", &length, &angle,&time) == 3)
	{
		printf("Reading BoneOrientation4 length=%f, angle=%f, time=%f\n", length, angle, time);
		orientation = new BoneOrientation(length, angle,time);
	}
	else if(sscanf(element, "(%f,%f)", &length, &angle) == 2)
	{
		printf("Reading BoneOrientation3\n");
		orientation = new BoneOrientation(length, angle);
	}
	
	return orientation;
}
BoneOrientation * SkeletonAnimationReader::ReadNextBoneOrientation(char * tag, int * pos)
{
	char * element = FileReader::GetNextElement(tag, pos);
	BoneOrientation * orientation = ReadBoneOrientation(element);
	if(element != NULL)
		free(element);
	element = NULL;
	return orientation;
}
int SkeletonAnimationReader::GetElementType(char * element)
{
	if(strcmp(element, "name")==0)
		return ANIMATION_NAME_TYPE;
	if(strcmp(element, "pose")==0)
		return POSE_TYPE;
	return UNKNOWN_TYPE;
}
